package com.njxxted.activiti.modules.process.task.handler;

import com.google.common.collect.Lists;
import com.njxxted.activiti.common.constant.Constant;
import com.njxxted.activiti.common.mode.IModeHandleService;
import com.njxxted.activiti.common.util.*;
import com.njxxted.activiti.modules.api.PushApi;
import com.njxxted.activiti.modules.api.entity.PushVo;
import com.njxxted.activiti.modules.process.cmd.TaskHandleCmd;
import com.njxxted.activiti.modules.process.defintion.dao.ActDefinitionDao;
import com.njxxted.activiti.modules.process.defintion.dao.ActRunDefinitionDao;
import com.njxxted.activiti.modules.process.defintion.entity.ActRunNodeConfigEntity;
import com.njxxted.activiti.modules.process.extend.dao.ExtendActCopyDao;
import com.njxxted.activiti.modules.process.extend.dao.ExtendActHistoryDao;
import com.njxxted.activiti.modules.process.extend.dao.ExtendActInstanceDao;
import com.njxxted.activiti.modules.process.extend.entity.ExtendActHistoryEntity;
import com.njxxted.activiti.modules.process.extend.entity.ExtendActInstanceEntity;
import com.njxxted.activiti.modules.process.extend.service.ExtendActInstanceService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.User;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述：策略模式 抽象处理接口类,其他业务实现类必须集成此类来实现策略
 * <p>
 * 作者：Ostrich Hu
 * 时间：2019/9/29 9:36 星期日
 */
public abstract class AbstractTaskStrategyHandler implements IModeHandleService {

    public final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    public TaskService taskService;
    @Resource
    public IdentityService identityService;
    @Resource
    public RuntimeService runtimeService;
    @Resource
    public HistoryService historyService;
    @Resource
    public ActDefinitionDao actDefinitionDao;
    @Resource
    public ActRunDefinitionDao actRunDefinitionDao;
    @Resource
    public ExtendActCopyDao extendActCopyDao;
    @Resource
    public ExtendActInstanceService extActPInstanceService;
    @Resource
    public ExtendActInstanceDao extendActInstanceDao;
    @Resource
    public ExtendActHistoryDao extendActHistoryDao;

    public abstract void taskHandle(TaskHandleCmd taskCmd);

    /**
     * 设置扩展信息
     */
    public void setExtendActEntity(String status, TaskHandleCmd taskCmd, String preId,
                                   String currId, String currName, Task nextTask) {
        ExtendActInstanceEntity instanceEntity = new ExtendActInstanceEntity();
        ExtendActHistoryEntity historyEntity = new ExtendActHistoryEntity();
        ExtendActHistoryEntity nextTaskHistoryEntity = new ExtendActHistoryEntity();
        //修改流程状态
        instanceEntity.setStatus(status);
        instanceEntity.setInstanceId(taskCmd.getInstanceId());
        instanceEntity.setRecentlyDoTime(new Date());
        instanceEntity.setBusinessId(taskCmd.getBusinessId());
        instanceEntity.setPreNodeId(preId);
        instanceEntity.setCurrNodeId(currId);
        instanceEntity.setCurrNodeName(currName);
        extendActInstanceDao.update(instanceEntity);

        //先根据流程实例id和当前taskId删除自定义流程历史
        extendActHistoryDao.deleteByPidTid(taskCmd.getInstanceId(), taskCmd.getCurrNodeId());
        //修改当前任务节点自定义的流程历史
        historyEntity.setId(StringUtils.uuidGenerator());
        historyEntity.setTaskId(taskCmd.getCurrNodeId());
        historyEntity.setTaskDefKey(taskCmd.getCurrNodeKey());
        historyEntity.setTaskName(taskCmd.getCurrNodeName());
        historyEntity.setProcessDefKey(taskCmd.getKey());
        historyEntity.setOperateType(status);
        historyEntity.setOperateUserId(taskCmd.getOperateUserId());
        historyEntity.setOperateComment(taskCmd.getComment());
        historyEntity.setBusinessId(taskCmd.getBusinessId());
        historyEntity.setProcessInstanceId(taskCmd.getInstanceId());
        historyEntity.setAddDate(new Date());
        extendActHistoryDao.save(historyEntity);
        //如果有下一节点则插入下一节点历史
        if (nextTask != null) {
            nextTaskHistoryEntity.setDeadline(nextTask.getDueDate());
            nextTaskHistoryEntity.setId(StringUtils.uuidGenerator());
            nextTaskHistoryEntity.setTaskId(nextTask.getId());
            nextTaskHistoryEntity.setTaskDefKey(nextTask.getTaskDefinitionKey());
            nextTaskHistoryEntity.setTaskName(nextTask.getName());
            nextTaskHistoryEntity.setProcessDefKey(taskCmd.getKey());
            nextTaskHistoryEntity.setBusinessId(taskCmd.getBusinessId());
            nextTaskHistoryEntity.setProcessInstanceId(taskCmd.getInstanceId());
            nextTaskHistoryEntity.setAddDate(new Date());
            extendActHistoryDao.save(nextTaskHistoryEntity);
        }
    }

    /**
     * 推送消息
     *
     * @param instanceId   流程实例id
     * @param processKey   流程定义key
     * @param instanceName 流程名称
     * @param nodeId       任务节点id
     * @param conditionMap 模板替换值
     */
    public void pushNotice(String instanceId, String processKey, String instanceName,
                           String nodeId, Map<String, Object> conditionMap) {
        List<PushVo> pushVoList = Lists.newArrayList();
        //流程运行时配置信息
        ActRunNodeConfigEntity nodeRunConfigEntity = new ActRunNodeConfigEntity();
        nodeRunConfigEntity.setKey(processKey);
        nodeRunConfigEntity.setNodeId(nodeId);
        nodeRunConfigEntity.setInstanceId(instanceId);
        //查询运行时配置信息
        List<ActRunNodeConfigEntity> runSettings = actRunDefinitionDao.getProcessDefinitionSettings(nodeRunConfigEntity);
        runSettings.forEach(nodeConfig -> {
            String configType = nodeConfig.getConfigType();
            String[] split = nodeConfig.getConfigValue().split("[/]");
            String acceptClientId = split[split.length - 1];
            switch (configType) {
                case Constant.Flow.ASSIGN_USER:
                    pushVoList.add(PushUtils.convertPushParam(acceptClientId, Constant.PushType.ASSIGN_NOTICE,
                            instanceName, instanceId, conditionMap));
                    break;
                case Constant.Flow.COPY_USER:
                    pushVoList.add(PushUtils.convertPushParam(acceptClientId, Constant.PushType.COPY_NOTICE,
                            instanceName, instanceId, conditionMap));
                    break;
            }

        });
        //过滤重复的推送信息
//        List<PushVo> collect = pushVoList.parallelStream().collect(Collectors.collectingAndThen(
//                Collectors.toCollection(
//                        () -> new TreeSet<>(
//                                Comparator.comparing(o -> o.getAcceptClientId() + o.getTypes())
//                        )
//                ),
//                ArrayList::new));
        //新增推送消息到消息推送信息表中
        new FeignUtil<PushApi>().invokeCommonService(PushApi.class)
                .messageSaveBatchForPush(JsonUtils.beanToJson(pushVoList));
    }
}
